package score.utils;

import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;

import javax.imageio.ImageIO;
import javax.swing.JFileChooser;

import score.BinaryImage;
import score.GrayScaleImage;
import score.IBinaryImage;
import score.IGrayScaleImage;
import score.IImage;
import score.IRGBImage;


public class ImageBuilder {
    /**
     * Carregando uma imagem do arquivo
     * @param path - caminho da imagem
     * @return BinaryImage
     */
    public static IBinaryImage loadImageBinary(String path) {
        return loadImageBinary(new File(path));
    }
    public static IGrayScaleImage loadImageGrayScale(String path) {
    	return loadImageGrayScale(new File(path));
    }

    /**
     * Carregando uma imagem do arquivo
     * @param path - caminho da imagem
     * @return BinaryImage
     */
    public static IGrayScaleImage loadImageGrayScale(File file) {
        IGrayScaleImage img = null;
        try {
        	BufferedImage image = ImageIO.read(file);
        	int width = image.getWidth(); 
            int height = image.getHeight();
            int pixels[][] = new int[width][height];
            if(image.getType() == BufferedImage.TYPE_BYTE_GRAY || image.getType() == BufferedImage.TYPE_BYTE_BINARY){
        		for(int w=0;w<width;w++){
                    for(int h=0;h<height;h++){
                        pixels[w][h] = image.getData().getSample(w, h, 0);
                    }
                }
        	}
        	else{
        		int rgb, r, g, b;
                for(int w=0;w<width;w++){
                    for(int h=0;h<height;h++){
                        rgb = image.getRGB(w,h);
                        r = (rgb >> 16) & 0xff;
                        g = (rgb >> 8) & 0xff;
                        b = (rgb) & 0xff;
                        //pixels[w][h] = (int) Math.round(.299*r + .587*g + .114*b); //convertendo para niveis de cinza
                        pixels[w][h] = (int) Math.round( (r + g + b) / 3); //convertendo para niveis de cinza
                    }
                } 
        	}
            img = new GrayScaleImage(pixels);
            
        } catch (IOException e) {
            throw new RuntimeException(file+ "\n"+ e.getMessage());
        }
        return img;
    }
    
    public static int[][] convertToArray(BufferedImage image){
        int width = image.getWidth();
        int height = image.getHeight();
        int pixels[][] = new int[width][height];
        if(image.getType() == BufferedImage.TYPE_BYTE_GRAY || image.getType() == BufferedImage.TYPE_BYTE_BINARY){
            for(int w=0;w<width;w++){
                for(int h=0;h<height;h++){
                    pixels[w][h] = image.getData().getSample(w, h, 0);
                }
            } 
        }else{
        	int rgb, r, g, b;
        	for(int w=0;w<width;w++){
        		for(int h=0;h<height;h++){
        			rgb = image.getRGB(w,h);
                
        			// int alpha = (rgb >> 24) & 0xff;
        			r = (rgb >> 16) & 0xff;
        			g = (rgb >> 8) & 0xff;
        			b = (rgb) & 0xff;
                
        			pixels[w][h] = (int) Math.round(.299*r + .587*g + .114*b); //convertendo para niveis de cinza
        			//pixels[w][h] = (int) Math.round( (r + g + b) / 3); //convertendo para niveis de cinza
        		}
        	}
        }
        return pixels;
    }
    
    
    
    

    public static int[][] convertToArrayHSI(BufferedImage image){
        int width = image.getWidth();
        int height = image.getHeight();
        int pixels[][] = new int[width][height];
        int rgb, r, g, b;
        for(int w=0;w<width;w++){
            for(int h=0;h<height;h++){
                rgb = image.getRGB(w,h);
                r = (int)((rgb&0x00FF0000)>>>16); // Red level
                g = (int)((rgb&0x0000FF00)>>>8); // Green level
                b = (int) (rgb&0x000000FF); // Blue level
                pixels[w][h] = (r + g + b) / 3;
            }
        } 
        return pixels;
    }
    
    public static int[][][] convertToArrayRGB(BufferedImage image){
        int width = image.getWidth();
        int height = image.getHeight();
        int pixels[][][] = new int[3][width][height];
        int rgb, r, g, b;
        for(int w=0;w<width;w++){
            for(int h=0;h<height;h++){
                rgb = image.getRGB(w,h);
                r = (int)((rgb&0x00FF0000)>>>16); // Red level
                g = (int)((rgb&0x0000FF00)>>>8); // Green level
                b = (int) (rgb&0x000000FF); // Blue level
                pixels[0][w][h] = r;
                pixels[1][w][h] = g;
                pixels[2][w][h] = b;
            }
        }
        return pixels;
    }

    public static Image convertToImageRGB(int [][][]pixels){
        return convertToImage(pixels);
    }
    
    public static BufferedImage convertToImage(int [][]pixels){
        int width = pixels.length;
        int height = pixels[0].length; 
        BufferedImage bi = new BufferedImage(width,height, BufferedImage.TYPE_BYTE_GRAY);
        for(int w=0;w<width;w++){
            for(int h=0;h<height;h++){
            	bi.setRGB(w, h, new Color(pixels[w][h], pixels[w][h], pixels[w][h]).getRGB());
            }
        }
        bi.getSource();
        return bi;
    }
    
    public static BufferedImage convertToImage(int [][][]pixels){
    	int width = pixels[0].length;
        int height = pixels[0][0].length; 
        BufferedImage bi = new BufferedImage(width,height, BufferedImage.TYPE_INT_BGR);
        for(int w=0;w<width;w++){
            for(int h=0;h<height;h++){
            	bi.setRGB(w, h, new Color(pixels[0][w][h], pixels[1][w][h], pixels[2][w][h]).getRGB());
            }
        }
        bi.getSource();
        return bi;
    }
    
    /**
     * Carregando uma imagem do arquivo
     * @param file - arquivo
     * @return BinaryImage
     */
    public static IBinaryImage loadImageBinary(File file) {
        IBinaryImage img = null;
        try {
            img = new BinaryImage(ImageIO.read(file));
        } catch (IOException e) {
            throw new RuntimeException(e.getMessage());
        }
        for (int i = 0; i < img.getWidth(); i++) {
            for (int j = 0; j < img.getHeight(); j++) {
                if (img.getPixel(i, j) > 150)
                    img.setPixel(i, j, 255);
                else
                    img.setPixel(i, j, 0);
            }
        }
        return img;
    }

    /**
     * salvando uma imagem
     * @param image
     * @throws IOException 
     */
    public static void saveImage(BufferedImage image, File file) {
        try {
            ImageIO.write(image,file.getName().substring(file.getName().length() - 3), file);
        } catch (IOException e) {
            e.printStackTrace();
        }        
    }


    /**
     * salvando uma imagem
     * @param image
     * @throws IOException 
     */
    public static void saveImage(IImage image, File file) {
        saveImage(image.createImage(), file);
    }
    
    
   	public static File windowOpenFile(){
   		JFileChooser fc = new JFileChooser();
   	    fc.setFileSelectionMode(JFileChooser.FILES_ONLY);
   	    int res = fc.showOpenDialog(null);
   	    return fc.getSelectedFile();
   	}
    
}
